package com.kakarote.hrm.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.core.common.MultipartFileUtil;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.cache.AdminCacheKey;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.UploadEntity;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.service.AdminFileService;
import com.kakarote.core.redis.Redis;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.ExcelParseUtil;
import com.kakarote.hrm.constant.RecruitPositionConstant;
import com.kakarote.hrm.constant.RecruitUserConstant;
import com.kakarote.hrm.constant.SexEnum;
import com.kakarote.hrm.entity.BO.QueryRecruitUserPageListBO;
import com.kakarote.hrm.entity.PO.HrmRecruitPlan;
import com.kakarote.hrm.entity.PO.HrmRecruitPlanRecord;
import com.kakarote.hrm.entity.PO.HrmRecruitPosition;
import com.kakarote.hrm.entity.PO.HrmRecruitUser;
import com.kakarote.hrm.entity.VO.RecruitPlanRecordVO;
import com.kakarote.hrm.entity.VO.RecruitUserExportVO;
import com.kakarote.hrm.entity.VO.RecruitUserVO;
import com.kakarote.hrm.mapper.HrmRecruitUserMapper;
import com.kakarote.hrm.service.IHrmRecruitPlanRecordService;
import com.kakarote.hrm.service.IHrmRecruitPlanService;
import com.kakarote.hrm.service.IHrmRecruitPositionService;
import com.kakarote.hrm.service.IHrmRecruitUserService;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 招聘人员 服务实现类
 * </p>
 *
 * @author system
 * @since 2024-01-01
 */
@Service
public class HrmRecruitUserServiceImpl extends BaseServiceImpl<HrmRecruitUserMapper, HrmRecruitUser> implements IHrmRecruitUserService {

    @Autowired
    private HrmRecruitUserMapper recruitUserMapper;
    @Autowired
    private HrmRecruitPlanRecordServiceImpl hrmRecruitPlanRecordService;
    @Autowired
    private IHrmRecruitPlanService hrmRecruitPlanService;
    @Autowired
    private IHrmRecruitPlanRecordService hrmRecruitPlanRecordService2;
    @Autowired
    private IHrmRecruitPositionService hrmRecruitPositionService;
    @Autowired
    private AdminFileService adminFileService;
    @Autowired
    private Redis redis;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog addRecruitUser(HrmRecruitUser recruitUser) {
        if (recruitUser.getRecordId() != null) {
            RecruitPlanRecordVO recruitPlanRecordVO = hrmRecruitPlanRecordService.queryById(recruitUser.getRecordId());
            if (recruitPlanRecordVO == null) {
                throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "计划记录不存在");
            }
            recruitUser.setPlanId(recruitPlanRecordVO.getPlanId());
        }
        if (StrUtil.isEmpty(recruitUser.getUserId())) {
            recruitUser.setUserId(UUID.randomUUID().toString());
        }
        save(recruitUser);

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(recruitUser.getRecruitUserId(), "招聘人员");
        String detail = String.format("招聘人员：%s，招聘人员编号：%s，岗位编号：%s",
                recruitUser.getRealName() != null ? recruitUser.getRealName() : "无",
                recruitUser.getUserId() != null ? recruitUser.getUserId() : "无",
                recruitUser.getPositionId() != null ? recruitUser.getPositionId().toString() : "无");
        operationLog.setOperationInfo(detail);
        operationLog.setBehavior(BehaviorEnum.SAVE);
        return operationLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog setRecruitUser(HrmRecruitUser recruitUser) {
        HrmRecruitUser oldUser = getById(recruitUser.getRecruitUserId());
        if (oldUser == null) {
            throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "招聘人员不存在");
        }
        if (recruitUser.getRecordId() != null) {
            RecruitPlanRecordVO recruitPlanRecordVO = hrmRecruitPlanRecordService.queryById(recruitUser.getRecordId());
            if (recruitPlanRecordVO == null) {
                throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "计划记录不存在");
            }
            recruitUser.setPlanId(recruitPlanRecordVO.getPlanId());
        } else {
            recruitUser.setPlanId(null);
        }

        // 记录变更内容
        StringBuilder detail = new StringBuilder();
        if (!Objects.equals(oldUser.getPlanId(), recruitUser.getPlanId())) {
            detail.append(String.format("计划编号：%s → %s；",
                    oldUser.getPlanId() != null ? oldUser.getPlanId().toString() : "无",
                    recruitUser.getPlanId() != null ? recruitUser.getPlanId().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getRecordId(), recruitUser.getRecordId())) {
            detail.append(String.format("记录编号：%s → %s；",
                    oldUser.getRecordId() != null ? oldUser.getRecordId().toString() : "无",
                    recruitUser.getRecordId() != null ? recruitUser.getRecordId().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getProcesId(), recruitUser.getProcesId())) {
            detail.append(String.format("过程编号：%s → %s；",
                    oldUser.getProcesId() != null ? oldUser.getProcesId().toString() : "无",
                    recruitUser.getProcesId() != null ? recruitUser.getProcesId().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getPositionId(), recruitUser.getPositionId())) {
            detail.append(String.format("岗位编号：%s → %s；",
                    oldUser.getPositionId() != null ? oldUser.getPositionId().toString() : "无",
                    recruitUser.getPositionId() != null ? recruitUser.getPositionId().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getUserId(), recruitUser.getUserId())) {
            detail.append(String.format("招聘人员编号：%s → %s；",
                    oldUser.getUserId() != null ? oldUser.getUserId() : "无",
                    recruitUser.getUserId() != null ? recruitUser.getUserId() : "无"));
        }
        if (!Objects.equals(oldUser.getRealName(), recruitUser.getRealName())) {
            detail.append(String.format("招聘人员名称：%s → %s；",
                    oldUser.getRealName() != null ? oldUser.getRealName() : "无",
                    recruitUser.getRealName() != null ? recruitUser.getRealName() : "无"));
        }
        if (!Objects.equals(oldUser.getSex(), recruitUser.getSex())) {
            detail.append(String.format("性别：%s → %s；",
                    oldUser.getSex() != null ? oldUser.getSex().toString() : "无",
                    recruitUser.getSex() != null ? recruitUser.getSex().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getChannel(), recruitUser.getChannel())) {
            detail.append(String.format("招聘渠道：%s → %s；",
                    oldUser.getChannel() != null ? oldUser.getChannel().toString() : "无",
                    recruitUser.getChannel() != null ? recruitUser.getChannel().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getAge(), recruitUser.getAge())) {
            detail.append(String.format("年龄：%s → %s；",
                    oldUser.getAge() != null ? oldUser.getAge().toString() : "无",
                    recruitUser.getAge() != null ? recruitUser.getAge().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getEducation(), recruitUser.getEducation())) {
            detail.append(String.format("学历：%s → %s；",
                    oldUser.getEducation() != null ? oldUser.getEducation().toString() : "无",
                    recruitUser.getEducation() != null ? recruitUser.getEducation().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getTechnicalLevel(), recruitUser.getTechnicalLevel())) {
            detail.append(String.format("专业技术职务类别：%s → %s；",
                    oldUser.getTechnicalLevel() != null ? oldUser.getTechnicalLevel().toString() : "无",
                    recruitUser.getTechnicalLevel() != null ? recruitUser.getTechnicalLevel().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getTechnologyType(), recruitUser.getTechnologyType())) {
            detail.append(String.format("技术工人类型：%s → %s；",
                    oldUser.getTechnologyType() != null ? oldUser.getTechnologyType().toString() : "无",
                    recruitUser.getTechnologyType() != null ? recruitUser.getTechnologyType().toString() : "无"));
        }
        if (!Objects.equals(oldUser.getPositionType(), recruitUser.getPositionType())) {
            detail.append(String.format("岗位类别：%s → %s；",
                    oldUser.getPositionType() != null ? oldUser.getPositionType().toString() : "无",
                    recruitUser.getPositionType() != null ? recruitUser.getPositionType().toString() : "无"));
        }

        updateById(recruitUser);

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(recruitUser.getRecruitUserId(), "招聘人员");
        operationLog.setOperationInfo(detail.toString());
        operationLog.setBehavior(BehaviorEnum.UPDATE);
        return operationLog;
    }

    @Override
    public RecruitUserVO queryById(Long recruitUserId) {
        return recruitUserMapper.queryById(recruitUserId);
    }

    @Override
    public BasePage<RecruitUserVO> queryRecruitUserPageList(QueryRecruitUserPageListBO queryRecruitUserPageListBO) {
        BasePage<RecruitUserVO> page = queryRecruitUserPageListBO.parse();
        return recruitUserMapper.queryRecruitUserPageList(page, queryRecruitUserPageListBO);
    }

    @Override
    public List<RecruitUserVO> queryByPlanId(Long planId) {
        return recruitUserMapper.queryByPlanId(planId);
    }

    @Override
    public List<RecruitUserVO> queryByRecordId(Long recordId) {
        return recruitUserMapper.queryByRecordId(recordId);
    }

    @Override
    public List<RecruitUserVO> queryByProcesId(Long procesId) {
        return recruitUserMapper.queryByProcesId(procesId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog deleteRecruitUser(Long recruitUserId) {
        HrmRecruitUser recruitUser = getById(recruitUserId);
        if (recruitUser == null) {
            throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "招聘人员不存在");
        }

        removeById(recruitUserId);
        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(recruitUserId, "招聘人员");
        operationLog.setOperationInfo(String.format("删除招聘人员，姓名：%s，招聘人员编号：%s",
                recruitUser.getRealName() != null ? recruitUser.getRealName() : "无",
                recruitUser.getUserId() != null ? recruitUser.getUserId() : "无"));
        operationLog.setBehavior(BehaviorEnum.DELETE);
        return operationLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog batchDeleteRecruitUser(List<Long> recruitUserIds) {
        if (recruitUserIds == null || recruitUserIds.isEmpty()) {
            throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "请选择要删除的招聘人员");
        }

        List<HrmRecruitUser> userList = listByIds(recruitUserIds);
        if (userList.isEmpty()) {
            throw new CrmException(SystemCodeEnum.SYSTEM_ERROR.getCode(), "选择的招聘人员不存在");
        }

        removeByIds(recruitUserIds);
        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(recruitUserIds.toString(), "批量删除招聘人员");
        StringBuilder detail = new StringBuilder("删除招聘人员：");
        for (HrmRecruitUser user : userList) {
            detail.append("姓名:").append(user.getRealName()).append("、");
        }
        if (detail.length() > 0) {
            detail.setLength(detail.length() - 1);
        }
        operationLog.setOperationInfo(detail.toString());
        operationLog.setBehavior(BehaviorEnum.DELETE);
        return operationLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog deleteByPlanId(Long planId) {
        Map<String, Object> params = new HashMap<>();
        params.put("plan_id", planId);
        List<HrmRecruitUser> userList = listByMap(params);
        if (!userList.isEmpty()) {
            recruitUserMapper.deleteByPlanId(planId);
        }

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(planId, "删除计划下所有招聘人员");
        operationLog.setOperationInfo(String.format("删除计划下所有招聘人员，共%d个", userList.size()));
        operationLog.setBehavior(BehaviorEnum.DELETE);
        return operationLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog deleteByRecordId(Long recordId) {
        Map<String, Object> params = new HashMap<>();
        params.put("record_id", recordId);
        List<HrmRecruitUser> userList = listByMap(params);
        if (!userList.isEmpty()) {
            recruitUserMapper.deleteByRecordId(recordId);
        }

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(recordId, "删除记录下所有招聘人员");
        operationLog.setOperationInfo(String.format("删除记录下所有招聘人员，共%d个", userList.size()));
        operationLog.setBehavior(BehaviorEnum.DELETE);
        return operationLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog deleteByProcesId(Long procesId) {
        Map<String, Object> params = new HashMap<>();
        params.put("proces_id", procesId);
        List<HrmRecruitUser> userList = listByMap(params);
        if (!userList.isEmpty()) {
            recruitUserMapper.deleteByProcesId(procesId);
        }

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(procesId, "删除过程下所有招聘人员");
        operationLog.setOperationInfo(String.format("删除过程下所有招聘人员，共%d个", userList.size()));
        operationLog.setBehavior(BehaviorEnum.DELETE);
        return operationLog;
    }

    @Override
    public void exportRecruitUser(HttpServletResponse response, QueryRecruitUserPageListBO queryRecruitUserPageListBO) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = "招聘人员_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
        response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));

        // 直接查询所有符合条件的数据（不分页）
        List<RecruitUserVO> dataList = recruitUserMapper.queryAllRecruitUserList(queryRecruitUserPageListBO);

        // 转换为导出VO
        List<RecruitUserExportVO> exportList = new ArrayList<>();
        for (RecruitUserVO vo : dataList) {
            RecruitUserExportVO exportVO = new RecruitUserExportVO();
            exportVO.setPlanName(vo.getPlanName());
            exportVO.setRecordCode(vo.getRecordCode());
            exportVO.setPositionName(vo.getPositionName());
            exportVO.setPositionCode(vo.getPositionCode());
            exportVO.setPositionUnit(vo.getPositionUnit());
            exportVO.setRealName(vo.getRealName());
            exportVO.setSexText(vo.getSex() == null ? null : SexEnum.parseName(vo.getSex()));
            exportVO.setChannelText(RecruitUserConstant.RecruitChannelEnum.valueOfName(vo.getChannel()));
            exportVO.setAge(vo.getAge());
            exportVO.setEducationText(RecruitUserConstant.EducationEnum.valueOfName(vo.getEducation()));
            exportVO.setTechnicalLevelText(RecruitUserConstant.TechnicalLevelEnum.valueOfName(vo.getTechnicalLevel()));
            exportVO.setTechnologyTypeText(RecruitUserConstant.TechnologyTypeEnum.valueOfName(vo.getTechnologyType()));
            exportVO.setPositionTypeText(RecruitPositionConstant.PositionTypeEnum.getNameByType(vo.getPositionType()));
            exportVO.setCreateTime(vo.getCreateTime());
            exportVO.setCreateRealName(vo.getCreateRealName());
            exportList.add(exportVO);
        }

        // 使用EasyExcel导出
        EasyExcel.write(response.getOutputStream(), RecruitUserExportVO.class)
                .sheet("招聘人员")
                .doWrite(exportList);
    }

    @Override
    public void downloadExcel(HttpServletResponse response) {
        List<JSONObject> list = queryField();
        ExcelParseUtil.importExcel(new ExcelParseUtil.ExcelParseService() {
            @Override
            public String getExcelName() {
                return "招聘人员";
            }

            @Override
            public String getMergeContent(String module) {
                return "注意事项：\n" +
                        "1、表头标“*”的红色字体为必填项\n" +
                        "2、导入只新增不修改\n" +
                        "3、计划名称和计划编号必须已存在\n" +
                        "4、记录编号必须已存在\n" +
                        "5、岗位名称和岗位编号必须已存在并匹配\n" +
                        "6、招聘人员名称不能为空\n" +
                        "7、性别只能填写[男、女]，或者不填\n" +
                        "8、招聘渠道只能填写[校招、社招]，或者不填\n" +
                        "9、年龄必须大于等于0\n" +
                        "10、学历只能填写[小学、初中、高中、中专、大专、大学、硕士研究生、博士研究生、无]，或者不填\n" +
                        "11、专业技术职务类别只能填写[初级、中级、正高级、高级]，或者不填\n" +
                        "12、技术工人类型只能填写[初级工、中级工、高级工、技师、高级技师]，或者不填\n" +
                        "13、岗位类别只能填写[管理岗、专技岗、工勤岗]，或者不填";
            }
        }, list, response, "user");
    }

    private List<JSONObject> queryField() {
        List<JSONObject> list = new ArrayList<>();
        list.add(queryField("planName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "计划名称", 1));
        list.add(queryField("planCode", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "计划编号", 1));
        list.add(queryField("recordCode", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "记录编号", 1));
        list.add(queryField("positionName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "岗位名称", 1));
        list.add(queryField("positionCode", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "岗位编号", 1));
        list.add(queryField("realName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "招聘人员名称", 1));
        list.add(queryField("sex", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "性别", 0));
        list.add(queryField("channel", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "招聘渠道", 0));
        list.add(queryField("age", FieldEnum.NUMBER.getFormType(), FieldEnum.NUMBER.getType(), "年龄", 0));
        list.add(queryField("education", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "学历", 0));
        list.add(queryField("technicalLevel", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "专业技术职务类别", 0));
        list.add(queryField("technologyType", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "技术工人类型", 0));
        list.add(queryField("positionType", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "岗位类别", 0));
        return list;
    }

    private JSONObject queryField(String fieldName, String formType, Integer type, String name, Integer isNull) {
        JSONObject json = new JSONObject();
        json.fluentPut("fieldName", fieldName)
                .fluentPut("formType", formType)
                .fluentPut("type", type)
                .fluentPut("name", name).fluentPut("isNull", isNull);
        return json;
    }

    private String getFilePath(MultipartFile file) {
        String dirPath = FileUtil.getTmpDirPath();
        try {
            InputStream inputStream = file.getInputStream();
            File fromStream = FileUtil.writeFromStream(inputStream, dirPath + "/" + IdUtil.simpleUUID() + file.getOriginalFilename());
            return fromStream.getAbsolutePath();
        } catch (IOException e) {
            throw new CrmException(SystemCodeEnum.SYSTEM_UPLOAD_FILE_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject excelImport(MultipartFile file) {
        List<List<Object>> errList = new ArrayList<>();
        String filePath = getFilePath(file);
        AtomicReference<Integer> num = new AtomicReference<>(0);
        //新增招聘人员
        List<HrmRecruitUser> addUserList = new ArrayList<>();
        //查询所有招聘计划
        List<HrmRecruitPlan> planList = hrmRecruitPlanService.list();
        Map<String, HrmRecruitPlan> planMap;
        if (planList != null && !planList.isEmpty()) {
            planMap = planList.stream().collect(Collectors.toMap(item -> Optional.ofNullable(item.getPlanName()).orElse("") + Optional.ofNullable(item.getPlanCode()).orElse(""), Function.identity(), (v1, v2) -> v1));
        } else {
            planMap = new HashMap<>();
        }
        //查询所有招聘记录
        List<HrmRecruitPlanRecord> recordList = hrmRecruitPlanRecordService2.list();
        Map<String, HrmRecruitPlanRecord> recordMap;
        if (recordList != null && !recordList.isEmpty()) {
            recordMap = recordList.stream().collect(Collectors.toMap(HrmRecruitPlanRecord::getRecordCode, Function.identity(), (v1, v2) -> v1));
        } else {
            recordMap = new HashMap<>();
        }
        //查询所有招聘岗位
        List<HrmRecruitPosition> positionList = hrmRecruitPositionService.list();
        Map<String, HrmRecruitPosition> positionMap;
        if (positionList != null && !positionList.isEmpty()) {
            positionMap = positionList.stream().collect(Collectors.toMap(item -> {
                Long planId = Optional.ofNullable(item.getPlanId()).orElse(0L);
                String positionName = Optional.ofNullable(item.getPositionName()).orElse("");
                String positionCode = Optional.ofNullable(item.getPositionCode()).orElse("");
                return planId + "_" + positionName + "_" + positionCode;
            }, Function.identity(), (v1, v2) -> v1));
        } else {
            positionMap = new HashMap<>();
        }

        ExcelUtil.readBySax(filePath, 0, (int sheetIndex, long rowIndex, List<Object> rowList) -> {
            if (rowIndex > 1) {
                num.getAndSet(num.get() + 1);
                if (rowList.size() < 14) {
                    int size = rowList.size();
                    for (int i = 0; i < 14 - size; i++) {
                        rowList.add("");
                    }
                }
                // 验证必填字段
                if (StrUtil.isEmptyIfStr(rowList.get(0).toString().trim())) {
                    rowList.add(0, "计划名称不能为空");
                    errList.add(rowList);
                    return;
                }
                if (StrUtil.isEmptyIfStr(rowList.get(1).toString().trim())) {
                    rowList.add(0, "计划编号不能为空");
                    errList.add(rowList);
                    return;
                }

                String planKey = rowList.get(0).toString().trim() + rowList.get(1).toString().trim();
                if (!planMap.containsKey(planKey)) {
                    rowList.add(0, "计划不存在");
                    errList.add(rowList);
                    return;
                }

                HrmRecruitPlan plan = planMap.get(planKey);
                if (plan == null) {
                    rowList.add(0, "计划不存在");
                    errList.add(rowList);
                    return;
                }

                // 验证记录编号
                if (StrUtil.isEmptyIfStr(rowList.get(2).toString().trim())) {
                    rowList.add(0, "记录编号不能为空");
                    errList.add(rowList);
                    return;
                }

                String recordCode = rowList.get(2).toString().trim();
                if (!recordMap.containsKey(recordCode)) {
                    rowList.add(0, "记录不存在");
                    errList.add(rowList);
                    return;
                }

                HrmRecruitPlanRecord record = recordMap.get(recordCode);
                if (record == null) {
                    rowList.add(0, "记录不存在");
                    errList.add(rowList);
                    return;
                }

                // 验证记录是否属于该计划
                if (!Objects.equals(record.getPlanId(), plan.getPlanId())) {
                    rowList.add(0, "记录不属于该计划");
                    errList.add(rowList);
                    return;
                }

                // 验证岗位名称
                if (StrUtil.isEmptyIfStr(rowList.get(3).toString().trim())) {
                    rowList.add(0, "岗位名称不能为空");
                    errList.add(rowList);
                    return;
                }

                if (StrUtil.isEmptyIfStr(rowList.get(4).toString().trim())) {
                    rowList.add(0, "岗位编号不能为空");
                    errList.add(rowList);
                    return;
                }

                String positionName = rowList.get(3).toString().trim();
                String positionCode = rowList.get(4).toString().trim();

                String positionKey = plan.getPlanId() + "_" + positionName + "_" + positionCode;
                if (!positionMap.containsKey(positionKey)) {
                    rowList.add(0, "岗位不存在");
                    errList.add(rowList);
                    return;
                }

                HrmRecruitPosition position = positionMap.get(positionKey);
                if (position == null) {
                    rowList.add(0, "岗位不存在");
                    errList.add(rowList);
                    return;
                }

                if (!Objects.equals(Optional.ofNullable(position.getPositionName()).orElse(""), positionName)) {
                    rowList.add(0, "岗位名称与编号不匹配");
                    errList.add(rowList);
                    return;
                }

                if (!Objects.equals(Optional.ofNullable(position.getPositionCode()).orElse(""), positionCode)) {
                    rowList.add(0, "岗位名称与编号不匹配");
                    errList.add(rowList);
                    return;
                }

                // 验证招聘人员名称
                if (StrUtil.isEmptyIfStr(rowList.get(5).toString().trim())) {
                    rowList.add(0, "招聘人员名称不能为空");
                    errList.add(rowList);
                    return;
                }

                String recruitUserName = rowList.get(5).toString().trim();
                // 验证性别
                Integer sex = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(6))) {
                    String sexStr = rowList.get(6).toString().trim();
                    if ("男".equals(sexStr)) {
                        sex = SexEnum.MAN.getValue();
                    } else if ("女".equals(sexStr)) {
                        sex = SexEnum.WOMAN.getValue();
                    } else {
                        rowList.add(0, "性别只能填写[男、女]");
                        errList.add(rowList);
                        return;
                    }
                }

                // 验证招聘渠道
                Integer channel = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(7))) {
                    String channelStr = rowList.get(7).toString().trim();
                    Integer channelValue = RecruitUserConstant.RecruitChannelEnum.valueOfType(channelStr);
                    if (channelValue == null) {
                        rowList.add(0, "招聘渠道只能填写[校招、社招]");
                        errList.add(rowList);
                        return;
                    }
                    channel = channelValue;
                }

                // 验证年龄
                Integer age = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(8))) {
                    try {
                        age = Integer.parseInt(rowList.get(8).toString().trim());
                        if (age < 0) {
                            rowList.add(0, "年龄必须大于等于0");
                            errList.add(rowList);
                            return;
                        }
                    } catch (NumberFormatException e) {
                        rowList.add(0, "年龄格式错误，必须为整数");
                        errList.add(rowList);
                        return;
                    }
                }

                // 验证学历
                Integer education = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(9))) {
                    String educationStr = rowList.get(9).toString().trim();
                    Integer educationValue = RecruitUserConstant.EducationEnum.valueOfType(educationStr);
                    if (educationValue == null) {
                        rowList.add(0, "学历只能填写[小学、初中、高中、中专、大专、大学、硕士研究生、博士研究生、无]");
                        errList.add(rowList);
                        return;
                    }
                    education = educationValue;
                }

                // 验证专业技术职务类别
                Integer technicalLevel = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(10))) {
                    String technicalLevelStr = rowList.get(10).toString().trim();
                    Integer technicalLevelValue = RecruitUserConstant.TechnicalLevelEnum.valueOfType(technicalLevelStr);
                    if (technicalLevelValue == null) {
                        rowList.add(0, "专业技术职务类别只能填写[初级、中级、正高级、高级]");
                        errList.add(rowList);
                        return;
                    }
                    technicalLevel = technicalLevelValue;
                }

                // 验证技术工人类型
                Integer technologyType = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(11))) {
                    String technologyTypeStr = rowList.get(11).toString().trim();
                    Integer technologyTypeValue = RecruitUserConstant.TechnologyTypeEnum.valueOfType(technologyTypeStr);
                    if (technologyTypeValue == null) {
                        rowList.add(0, "技术工人类型只能填写[初级工、中级工、高级工、技师、高级技师]");
                        errList.add(rowList);
                        return;
                    }
                    technologyType = technologyTypeValue;
                }

                // 验证岗位类别
                Integer positionType = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(12))) {
                    String positionTypeStr = rowList.get(12).toString().trim();
                    Integer positionTypeValue = RecruitPositionConstant.PositionTypeEnum.getTypeByName(positionTypeStr);
                    if (positionTypeValue == null) {
                        rowList.add(0, "岗位类别只能填写[管理岗、专技岗、工勤岗]");
                        errList.add(rowList);
                        return;
                    }
                    positionType = positionTypeValue;
                }

                HrmRecruitUser user = new HrmRecruitUser();
                user.setPlanId(plan.getPlanId());
                user.setRecordId(record.getRecordId());
                user.setPositionId(position.getPositionId());
                user.setUserId(UUID.randomUUID().toString());
                user.setRealName(recruitUserName);
                user.setSex(sex);
                user.setChannel(channel);
                user.setAge(age);
                user.setEducation(education);
                user.setTechnicalLevel(technicalLevel);
                user.setTechnologyType(technologyType);
                user.setPositionType(positionType);
                user.setCreateTime(LocalDateTime.now());
                addUserList.add(user);
            } else {
                if (rowIndex == 1) {
                    rowList.add(0, "错误信息");
                }
                errList.add(Convert.toInt(rowIndex), rowList);
            }
        });

        if (!addUserList.isEmpty()) {
            this.saveBatch(addUserList);
        }
        FileUtil.del(filePath);
        JSONObject result = new JSONObject().fluentPut("totalSize", num.get()).fluentPut("errSize", 0);
        int listSize = 2;
        if (errList.size() > listSize) {
            File errFile = FileUtil.file("excelData/" + IdUtil.simpleUUID() + ".xlsx");
            BigExcelWriter writer = ExcelUtil.getBigWriter(errFile);
            // 取消数据的黑色边框以及数据左对齐
            CellStyle cellStyle = writer.getCellStyle();
            cellStyle.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyle.setBorderTop(BorderStyle.NONE);
            cellStyle.setBorderBottom(BorderStyle.NONE);
            cellStyle.setBorderLeft(BorderStyle.NONE);
            cellStyle.setBorderRight(BorderStyle.NONE);
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
            Font defaultFont = writer.createFont();
            defaultFont.setFontHeightInPoints((short) 11);
            cellStyle.setFont(defaultFont);
            // 取消数字格式的数据的黑色边框以及数据左对齐
            CellStyle cellStyleForNumber = writer.getStyleSet().getCellStyleForNumber();
            cellStyleForNumber.setBorderTop(BorderStyle.NONE);
            cellStyleForNumber.setBorderBottom(BorderStyle.NONE);
            cellStyleForNumber.setBorderLeft(BorderStyle.NONE);
            cellStyleForNumber.setBorderRight(BorderStyle.NONE);
            cellStyleForNumber.setAlignment(HorizontalAlignment.LEFT);
            cellStyleForNumber.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyleForNumber.setFont(defaultFont);

            CellStyle textStyle = writer.getWorkbook().createCellStyle();
            DataFormat format = writer.getWorkbook().createDataFormat();
            textStyle.setDataFormat(format.getFormat("@"));

            writer.merge(errList.get(1).size() + 1, errList.get(0).get(0).toString().trim(), true);
            writer.getHeadCellStyle().setAlignment(HorizontalAlignment.LEFT);
            writer.getHeadCellStyle().setWrapText(true);
            Font headFont = writer.createFont();
            headFont.setFontHeightInPoints((short) 11);
            writer.getHeadCellStyle().setFont(headFont);
            writer.getHeadCellStyle().setFillPattern(FillPatternType.NO_FILL);
            writer.getOrCreateRow(0).setHeightInPoints(120);
            writer.setRowHeight(-1, 20);

            for (int i = 0; i < errList.get(1).size(); i++) {
                writer.getSheet().setDefaultColumnStyle(i, textStyle);
            }
            errList.remove(0);
            writer.write(errList);
            writer.close();
            //将错误信息的excel保存七天 604800 七天的秒数
            MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(errFile);
            UploadEntity uploadEntity = adminFileService.uploadTempFile(multipartFile, IdUtil.simpleUUID()).getData();

            redis.setex(AdminCacheKey.UPLOAD_EXCEL_MESSAGE_PREFIX + "file:" + uploadEntity.getFileId(), 604800, uploadEntity.getPath());

            result.fluentPut("errSize", errList.size() - 1).fluentPut("token", uploadEntity.getFileId());
        }
        return result;
    }

    @Override
    public UploadEntity uploadTempFile(MultipartFile file, String batchId) {
        Result<UploadEntity> result = adminFileService.uploadTempFile(file, batchId);
        return result.getData();
    }
}

